import 'package:equatable/equatable.dart';

/// 待办状态枚举
enum TodoStatus {
  todo('TODO', '待处理'),
  inProgress('IN_PROGRESS', '进行中'),
  done('DONE', '已完成'),
  blocked('BLOCKED', '阻塞');

  const TodoStatus(this.code, this.description);
  final String code;
  final String description;

  static TodoStatus fromCode(String code) {
    return TodoStatus.values.firstWhere(
      (status) => status.code == code,
      orElse: () => TodoStatus.todo,
    );
  }
}

/// 待办类型枚举
enum TodoType {
  communication('COMMUNICATION', '沟通确认'),
  schedule('SCHEDULE', '排期安排'),
  document('DOCUMENT', '文档编写'),
  dataSource('DATA_SOURCE', '数据源核查'),
  develop('DEVELOP', '开发实现'),
  test('TEST', '测试验证'),
  uat('UAT', 'UAT验收'),
  release('RELEASE', '发布上线');

  const TodoType(this.code, this.description);
  final String code;
  final String description;

  static TodoType fromCode(String code) {
    return TodoType.values.firstWhere(
      (type) => type.code == code,
      orElse: () => TodoType.develop,
    );
  }
}

/// 优先级枚举（与项目共用）
enum Priority {
  high('HIGH', '高'),
  medium('MEDIUM', '中'),
  low('LOW', '低');

  const Priority(this.code, this.description);
  final String code;
  final String description;

  static Priority fromCode(String code) {
    return Priority.values.firstWhere(
      (priority) => priority.code == code,
      orElse: () => Priority.medium,
    );
  }
}

/// 待办任务数据模型
class TodoModel extends Equatable {
  final int id;
  final int projectId;
  final String? projectName;
  final String title;
  final String? description;
  final TodoStatus status;
  final Priority priority;
  final TodoType todoType;
  final int? assigneeId;
  final String? assigneeName;
  final int reporterId;
  final String? reporterName;
  final DateTime? dueDate;
  final double? estimatedHours;
  final double? actualHours;
  final DateTime createTime;
  final DateTime? updateTime;
  final bool isOverdue;
  final int progress;

  const TodoModel({
    required this.id,
    required this.projectId,
    this.projectName,
    required this.title,
    this.description,
    required this.status,
    required this.priority,
    required this.todoType,
    this.assigneeId,
    this.assigneeName,
    required this.reporterId,
    this.reporterName,
    this.dueDate,
    this.estimatedHours,
    this.actualHours,
    required this.createTime,
    this.updateTime,
    this.isOverdue = false,
    this.progress = 0,
  });

  factory TodoModel.fromJson(Map<String, dynamic> json) {
    return TodoModel(
      id: json['id'] as int,
      projectId: json['projectId'] as int,
      projectName: json['projectName'] as String?,
      title: json['title'] as String,
      description: json['description'] as String?,
      status: TodoStatus.fromCode(json['status'] as String),
      priority: Priority.fromCode(json['priority'] as String),
      todoType: TodoType.fromCode(json['todoType'] as String),
      assigneeId: json['assigneeId'] as int?,
      assigneeName: json['assigneeName'] as String?,
      reporterId: json['reporterId'] as int,
      reporterName: json['reporterName'] as String?,
      dueDate: json['dueDate'] != null
          ? DateTime.parse(json['dueDate'] as String)
          : null,
      estimatedHours: (json['estimatedHours'] as num?)?.toDouble(),
      actualHours: (json['actualHours'] as num?)?.toDouble(),
      createTime: DateTime.parse(json['createTime'] as String),
      updateTime: json['updateTime'] != null
          ? DateTime.parse(json['updateTime'] as String)
          : null,
      isOverdue: json['isOverdue'] as bool? ?? false,
      progress: json['progress'] as int? ?? 0,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'projectId': projectId,
      'projectName': projectName,
      'title': title,
      'description': description,
      'status': status.code,
      'priority': priority.code,
      'todoType': todoType.code,
      'assigneeId': assigneeId,
      'assigneeName': assigneeName,
      'reporterId': reporterId,
      'reporterName': reporterName,
      'dueDate': dueDate?.toIso8601String(),
      'estimatedHours': estimatedHours,
      'actualHours': actualHours,
      'createTime': createTime.toIso8601String(),
      'updateTime': updateTime?.toIso8601String(),
      'isOverdue': isOverdue,
      'progress': progress,
    };
  }

  TodoModel copyWith({
    int? id,
    int? projectId,
    String? projectName,
    String? title,
    String? description,
    TodoStatus? status,
    Priority? priority,
    TodoType? todoType,
    int? assigneeId,
    String? assigneeName,
    int? reporterId,
    String? reporterName,
    DateTime? dueDate,
    double? estimatedHours,
    double? actualHours,
    DateTime? createTime,
    DateTime? updateTime,
    bool? isOverdue,
    int? progress,
  }) {
    return TodoModel(
      id: id ?? this.id,
      projectId: projectId ?? this.projectId,
      projectName: projectName ?? this.projectName,
      title: title ?? this.title,
      description: description ?? this.description,
      status: status ?? this.status,
      priority: priority ?? this.priority,
      todoType: todoType ?? this.todoType,
      assigneeId: assigneeId ?? this.assigneeId,
      assigneeName: assigneeName ?? this.assigneeName,
      reporterId: reporterId ?? this.reporterId,
      reporterName: reporterName ?? this.reporterName,
      dueDate: dueDate ?? this.dueDate,
      estimatedHours: estimatedHours ?? this.estimatedHours,
      actualHours: actualHours ?? this.actualHours,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      isOverdue: isOverdue ?? this.isOverdue,
      progress: progress ?? this.progress,
    );
  }

  /// 距离截止日期的天数
  int? get daysUntilDue {
    if (dueDate == null) return null;
    final now = DateTime.now();
    final difference = dueDate!.difference(now).inDays;
    return difference;
  }

  /// 获取状态颜色
  String get statusColor {
    switch (status) {
      case TodoStatus.todo:
        return '#6B7280'; // gray
      case TodoStatus.inProgress:
        return '#3B82F6'; // blue
      case TodoStatus.done:
        return '#10B981'; // green
      case TodoStatus.blocked:
        return '#EF4444'; // red
    }
  }

  /// 获取优先级颜色
  String get priorityColor {
    switch (priority) {
      case Priority.high:
        return '#EF4444'; // red
      case Priority.medium:
        return '#F59E0B'; // yellow
      case Priority.low:
        return '#10B981'; // green
    }
  }

  @override
  List<Object?> get props => [
        id,
        projectId,
        projectName,
        title,
        description,
        status,
        priority,
        todoType,
        assigneeId,
        assigneeName,
        reporterId,
        reporterName,
        dueDate,
        estimatedHours,
        actualHours,
        createTime,
        updateTime,
        isOverdue,
        progress,
      ];
}

/// 待办创建请求模型
class TodoCreateRequest extends Equatable {
  final int projectId;
  final String title;
  final String? description;
  final Priority priority;
  final TodoType todoType;
  final int? assigneeId;
  final DateTime? dueDate;
  final double? estimatedHours;

  const TodoCreateRequest({
    required this.projectId,
    required this.title,
    this.description,
    this.priority = Priority.medium,
    required this.todoType,
    this.assigneeId,
    this.dueDate,
    this.estimatedHours,
  });

  Map<String, dynamic> toJson() {
    return {
      'projectId': projectId,
      'title': title,
      'description': description,
      'priority': priority.code,
      'todoType': todoType.code,
      'assigneeId': assigneeId,
      'dueDate': dueDate?.toIso8601String(),
      'estimatedHours': estimatedHours,
    };
  }

  @override
  List<Object?> get props => [
        projectId,
        title,
        description,
        priority,
        todoType,
        assigneeId,
        dueDate,
        estimatedHours,
      ];
}

/// 待办更新请求模型
class TodoUpdateRequest extends Equatable {
  final String? title;
  final String? description;
  final TodoStatus? status;
  final Priority? priority;
  final TodoType? todoType;
  final int? assigneeId;
  final DateTime? dueDate;
  final double? estimatedHours;
  final double? actualHours;

  const TodoUpdateRequest({
    this.title,
    this.description,
    this.status,
    this.priority,
    this.todoType,
    this.assigneeId,
    this.dueDate,
    this.estimatedHours,
    this.actualHours,
  });

  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{};

    if (title != null) json['title'] = title;
    if (description != null) json['description'] = description;
    if (status != null) json['status'] = status!.code;
    if (priority != null) json['priority'] = priority!.code;
    if (todoType != null) json['todoType'] = todoType!.code;
    if (assigneeId != null) json['assigneeId'] = assigneeId;
    if (dueDate != null) json['dueDate'] = dueDate!.toIso8601String();
    if (estimatedHours != null) json['estimatedHours'] = estimatedHours;
    if (actualHours != null) json['actualHours'] = actualHours;

    return json;
  }

  @override
  List<Object?> get props => [
        title,
        description,
        status,
        priority,
        todoType,
        assigneeId,
        dueDate,
        estimatedHours,
        actualHours,
      ];
}
